﻿using Generic.App.Application.Contracts.Service;
using Generic.App.HttpApi.Options;
using Generic.Domain.Shared.Result;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Caching.Distributed;
using Microsoft.Extensions.Options;
using System.Text.Json;
using Volo.Abp.Caching;

namespace VP.Onboarding.HttpApi.Middleware
{
    public class TokenGreyMiddleware
    {
        private readonly RequestDelegate _next;
        private readonly IDistributedCache<List<string>, string>? _tokenGreyCache;
        private readonly IAppTokenGreyService? _appTokenGreyService;
        private readonly IOptions<CacheOptions>? _cacheOptions;

        public TokenGreyMiddleware(RequestDelegate next, IApplicationBuilder app)
        {
            _next = next;
            _tokenGreyCache = (IDistributedCache<List<string>, string>?)app.ApplicationServices.GetService(typeof(IDistributedCache<List<string>, string>));
            _appTokenGreyService = (IAppTokenGreyService?)app.ApplicationServices.GetService(typeof(IAppTokenGreyService));
            _cacheOptions = (IOptions<CacheOptions>?)app.ApplicationServices.GetService(typeof(IOptions<CacheOptions>));
        }

        public async Task Invoke(HttpContext context)
        {
            if (context.Request.Headers.ContainsKey("Authorization"))
            {
                var authorization = context.Request.Headers["Authorization"].ToString().Replace("Bearer ", "", StringComparison.OrdinalIgnoreCase);
                var greyTokens = await getGreyTokens();
                if (greyTokens.Contains(authorization))
                {
                    context.Response.ContentType = "application/json; charset=utf-8 ";
                    var stream = context.Response.Body;
                    await JsonSerializer.SerializeAsync(stream, new CustomResult { Code = CustomResultCode.系统异常.To<int>().ToString(), Message = "request abnormal" }
                    , new JsonSerializerOptions
                    {
                        PropertyNamingPolicy = JsonNamingPolicy.CamelCase
                    });
                    return;
                }

            }
            await _next(context);
        }

        private async Task<List<string>> getGreyTokens()
        {
            if (_tokenGreyCache != null && _appTokenGreyService != null)
            {
                var list =
                await _tokenGreyCache.GetOrAddAsync("TokenGrey",
                async () => await _appTokenGreyService.GetTokenGreyListAsync(),
                () =>
                {
                    return new DistributedCacheEntryOptions
                    {
                        AbsoluteExpiration = DateTime.Now.AddSeconds(_cacheOptions?.Value.TokenGreyTime ?? 0)
                    };
                });
                return list;
            }
            return new List<string>();
        }
    }
}
